package com.bawei.module_publish.ui

import android.annotation.SuppressLint
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ActivityInfo
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.hardware.SensorManager
import android.opengl.GLSurfaceView
import android.util.Log
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.OrientationEventListener
import android.view.ScaleGestureDetector
import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.CompoundButton
import android.widget.EditText
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import com.alibaba.android.arouter.facade.annotation.Route
import com.bawei.lib_mvi.base.BaseActivity
import com.bawei.module_publish.R
import com.bawei.module_publish.databinding.ActivityVideoRecordBinding
import com.bawei.module_publish.utils.Config
import com.bawei.module_publish.utils.GetPathFromUri
import com.bawei.module_publish.utils.MediaStoreUtils
import com.bawei.module_publish.utils.RecordSettings
import com.bawei.module_publish.utils.RecordSettings.RECORD_SPEED_ARRAY
import com.bawei.module_publish.utils.RecordSettings.chooseCameraFacingId
import com.bawei.module_publish.weiget.CustomProgressDialog
import com.bawei.module_publish.weiget.SectionProgressBar
import com.blankj.utilcode.util.ToastUtils
import com.qiniu.pili.droid.shortvideo.PLAudioEncodeSetting
import com.qiniu.pili.droid.shortvideo.PLCameraSetting
import com.qiniu.pili.droid.shortvideo.PLDraftBox
import com.qiniu.pili.droid.shortvideo.PLFaceBeautySetting
import com.qiniu.pili.droid.shortvideo.PLMicrophoneSetting
import com.qiniu.pili.droid.shortvideo.PLRecordSetting
import com.qiniu.pili.droid.shortvideo.PLRecordStateListener
import com.qiniu.pili.droid.shortvideo.PLScreenRecorder
import com.qiniu.pili.droid.shortvideo.PLScreenRecorderSetting
import com.qiniu.pili.droid.shortvideo.PLShortVideoRecorder
import com.qiniu.pili.droid.shortvideo.PLVideoEncodeSetting
import com.qiniu.pili.droid.shortvideo.PLVideoFrame
import com.qiniu.pili.droid.shortvideo.PLVideoSaveListener
import com.qiniu.pili.droid.shortvideo.PLWatermarkSetting
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min


@Route(path = "/publish/VideoRecordActivity")
class VideoRecordActivity : BaseActivity(), PLRecordStateListener, PLVideoSaveListener {

    private val TAG = "AudioRecordActivity"

    companion object {
        const val DRAFT = "draft";
    }


    private val binding: ActivityVideoRecordBinding by lazy {
        ActivityVideoRecordBinding.inflate(layoutInflater)
    }


    private lateinit var mShortVideoRecorder: PLShortVideoRecorder
    private lateinit var mProcessingDialog: CustomProgressDialog
    private lateinit var mSpeedTextView: TextView


    private var mFlashEnabled = false
    private var mIsEditVideo = false
    private var mMusicLoop = true

    private lateinit var mCameraSetting: PLCameraSetting
    private lateinit var mMicrophoneSetting: PLMicrophoneSetting
    private lateinit var mRecordSetting: PLRecordSetting
    private lateinit var mVideoEncodeSetting: PLVideoEncodeSetting
    private lateinit var mAudioEncodeSetting: PLAudioEncodeSetting
    private lateinit var mFaceBeautySetting: PLFaceBeautySetting
    private lateinit var mWatermarkSetting: PLWatermarkSetting
    private lateinit var mScreenRecorder: PLScreenRecorder
    private lateinit var screenSetting: PLScreenRecorderSetting

    private var mFocusIndicatorX = 0
    private var mFocusIndicatorY = 0
    private var zoomIndex = 0

    private var mRecordSpeed = 0.0

    private lateinit var mOrientationListener: OrientationEventListener
    private var mSectionBegan = false

    private lateinit var prefs: SharedPreferences


    override fun getLayoutRootView(): View {
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN
        )
        return binding.root
    }


    @SuppressLint("ClickableViewAccessibility")
    override fun initView() {

        prefs = applicationContext.getSharedPreferences(ConfigActivity.SP_NAME, MODE_PRIVATE)

        mSpeedTextView = findViewById(R.id.normal_speed_text)
        mProcessingDialog = CustomProgressDialog(this)
        mProcessingDialog.setOnCancelListener { dialog -> mShortVideoRecorder.cancelConcat() }

        mShortVideoRecorder = PLShortVideoRecorder()
        mShortVideoRecorder.setRecordStateListener(this)
        mRecordSpeed = RECORD_SPEED_ARRAY.get(2)
        mScreenRecorder.requestScreenRecord()
        screenSetting = PLScreenRecorderSetting()


        val draftTag = intent.getStringExtra(DRAFT)
        if (draftTag == null) {
            setCameraSetting()
            setVideoEncodeSetting()
            setMicrophoneSetting()
            setAudioEncodeSetting()
            setRecordSetting()
            setFaceBeautySetting()
            prepareAndSetShortVideoRecorder(binding.preview)
            onSectionCountChanged(0, 0)
        } else {
            val draftBox = PLDraftBox.getInstance(this)
            val draft = draftBox.getDraftByTag(draftTag)
            if (draft == null) {
                ToastUtils.showLong(getString(R.string.toast_draft_recover_fail))
                draftBox.removeDraftByTag(draftTag, false)
                finish()
                return
            }

            mCameraSetting = draft.cameraSetting
            mMicrophoneSetting = draft.microphoneSetting
            mVideoEncodeSetting = draft.videoEncodeSetting
            mAudioEncodeSetting = draft.audioEncodeSetting
            mRecordSetting = draft.recordSetting
            mFaceBeautySetting = draft.faceBeautySetting

            if (mShortVideoRecorder.recoverFromDraft(binding.preview, draft)) {
                var draftDuration: Long = 0
                for (i in 0 until draft.sectionCount) {
                    val currentDuration = draft.getSectionDuration(i)
                    draftDuration += draft.getSectionDuration(i)
                    onSectionIncreased(currentDuration, draftDuration, i + 1)
                }
                ToastUtils.showLong(getString(R.string.toast_draft_recover_success))
            } else {
                onSectionCountChanged(0, 0)
                ToastUtils.showLong(getString(R.string.toast_draft_recover_fail))
            }
        }

        mShortVideoRecorder.setRecordSpeed(mRecordSpeed)
        binding.recordProgressbar.setProceedingSpeed(mRecordSpeed)
        binding.recordProgressbar.setFirstPointTime(ConfigActivity.DEFAULT_MIN_RECORD_DURATION)
        binding.recordProgressbar.setTotalTime(mRecordSetting.maxRecordDuration)
        mScreenRecorder.prepare(screenSetting, mMicrophoneSetting);
        val mGestureDetector = GestureDetector(this, object : SimpleOnGestureListener() {
            override fun onSingleTapUp(e: MotionEvent): Boolean {
                mFocusIndicatorX = e.x.toInt() - binding.focusIndicator.width / 2
                mFocusIndicatorY = e.y.toInt() - binding.focusIndicator.height / 2
                mShortVideoRecorder.manualFocus(
                    binding.focusIndicator.width,
                    binding.focusIndicator.height,
                    e.x.toInt(),
                    e.y.toInt()
                )
                return false
            }
        })

        val mScaleGestureDetector =
            ScaleGestureDetector(this, object : SimpleOnScaleGestureListener() {
                override fun onScale(detector: ScaleGestureDetector): Boolean {
                    updateZoom(detector)
                    return true
                }
            })

        binding.preview.setOnTouchListener { view, motionEvent ->
            if (motionEvent.pointerCount == 1) {
                mGestureDetector.onTouchEvent(motionEvent)
            } else {
                mScaleGestureDetector.onTouchEvent(motionEvent)
            }
            true
        }

        mOrientationListener =
            object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
                override fun onOrientationChanged(orientation: Int) {
                    val rotation = getScreenRotation(orientation)
                    if (!binding.recordProgressbar.isRecorded && !mSectionBegan) {
                        mVideoEncodeSetting.setRotationInMetadata(rotation)
                    }
                }
            }

        if (mOrientationListener.canDetectOrientation()) {
            mOrientationListener.enable()
        }

    }

    private fun updateZoom(detector: ScaleGestureDetector) {
        val zooms = mShortVideoRecorder.zooms
        val maxIndex = zooms.size - 1
        val delta = detector.scaleFactor - 1
        val deltaIndex = (maxIndex * delta).toInt()
        val curIndex = zoomIndex
        zoomIndex += deltaIndex
        if (zoomIndex < 0) {
            zoomIndex = 0
        } else if (zoomIndex > maxIndex) {
            zoomIndex = maxIndex
        }
        val bigIndex = max(zoomIndex.toDouble(), curIndex.toDouble()).toInt()
        val smallIndex = min(zoomIndex.toDouble(), curIndex.toDouble()).toInt()
        for (i in smallIndex until bigIndex) {
            mShortVideoRecorder.setZoom(zooms[i])
        }
    }

    override fun initEvent() {
        //静音切换
        binding.muteSwitch.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
            if (isChecked) {
                mShortVideoRecorder.mute(true)
            } else {
                mShortVideoRecorder.mute(false)
            }
        })
        //录制
        binding.record.setOnClickListener(View.OnClickListener { v: View? ->
            if (mSectionBegan) {
                mShortVideoRecorder.endSection()
            } else {
                if (!mShortVideoRecorder.beginSection()) {
                    ToastUtils.showLong("无法开始视频段录制")
                }
            }
        })
        //白平衡
        binding.whiteBalance.setOnClickListener {
            val wbs = mShortVideoRecorder.supportedWhiteBalanceMode.toTypedArray<String>()
            AlertDialog.Builder(this).setItems(
                wbs
            ) { dialog: DialogInterface?, which: Int ->
                mShortVideoRecorder.setWhiteBalanceMode(
                    wbs[which]
                )
            }.show()
        }
        //删除
        binding.delete.setOnClickListener {
            if (!mShortVideoRecorder.deleteLastSection()) {
                ToastUtils.showLong("回删视频段失败")
            }
        }
        //保存
        binding.concat.setOnClickListener {
            mProcessingDialog.show()
            mProcessingDialog.progress = 0
            showChooseDialog()
        }
        //亮度调节
        binding.brightness.setOnClickListener {
            val isVisible = binding.adjustBrightness.visibility == View.VISIBLE
            binding.adjustBrightness.visibility = if (isVisible) View.GONE else View.VISIBLE
            if (mShortVideoRecorder != null) {
                mShortVideoRecorder.setAutoExposure(isVisible)
            }
        }
        //相机切换
        binding.switchCamera.setOnClickListener {
            mShortVideoRecorder.switchCamera()
            binding.focusIndicator.focusCancel()
        }
        //闪光灯
        binding.switchFlash.setOnClickListener {
            mFlashEnabled = !mFlashEnabled
            mShortVideoRecorder.setFlashEnabled(mFlashEnabled)
            binding.switchFlash.setActivated(mFlashEnabled)
        }
        //混音
        binding.mixAudio.setOnClickListener {
            AlertDialog.Builder(this)
                .setItems(arrayOf("循环", "单次")) { dialog: DialogInterface?, which: Int ->
                    mMusicLoop = which == 0
                    val intent = Intent()
                    intent.setAction(Intent.ACTION_OPEN_DOCUMENT)
                    intent.setType("audio/*")
                    intent.addCategory(Intent.CATEGORY_OPENABLE)
                    startActivityForResult(intent, 0)
                }
                .show()
        }
        //草稿箱
        binding.draft.setOnClickListener {
            val editText = EditText(this)
            AlertDialog.Builder(this)
                .setView(editText)
                .setTitle(getString(R.string.dlg_save_draft_title))
                .setPositiveButton(
                    getString(R.string.dlg_save_draft_yes)
                ) { dialogInterface: DialogInterface?, i: Int ->
                    ToastUtils.showLong(
                        if (mShortVideoRecorder.saveToDraftBox(editText.text.toString())) getString(
                            R.string.toast_draft_save_success
                        ) else getString(R.string.toast_draft_save_fail)
                    )
                }
                .show()
        }
    }

    private fun setCameraSetting() {
        val previewSizeRatioPos = prefs.getInt(
            ConfigActivity.KEY_PREVIEW_SIZE_RATIO_POS,
            ConfigActivity.DEFAULT_PREVIEW_SIZE_RATIO_POS
        )
        val previewSizeRatio = RecordSettings.PREVIEW_SIZE_RATIO_ARRAY[previewSizeRatioPos]
        val previewSizeLevelPos = prefs.getInt(
            ConfigActivity.KEY_PREVIEW_SIZE_LEVEL_POS,
            ConfigActivity.DEFAULT_PREVIEW_SIZE_LEVEL_POS
        )
        val previewSizeLevel = RecordSettings.PREVIEW_SIZE_LEVEL_ARRAY[previewSizeLevelPos]

        mCameraSetting = PLCameraSetting()
        val facingId: PLCameraSetting.CAMERA_FACING_ID = chooseCameraFacingId()
        mCameraSetting.setCameraId(facingId)
        mCameraSetting.setCameraPreviewSizeRatio(previewSizeRatio)
        mCameraSetting.setCameraPreviewSizeLevel(previewSizeLevel)
    }

    private fun setVideoEncodeSetting() {
        val encodeSizeLevelPos = prefs.getInt(
            ConfigActivity.KEY_VIDEO_ENCODE_SIZE_LEVEL_POS,
            ConfigActivity.DEFAULT_VIDEO_ENCODE_SIZE_LEVEL_POS
        )
        val encodingSizeLevel = RecordSettings.ENCODING_SIZE_LEVEL_ARRAY[encodeSizeLevelPos]
        val encodeBitrateLevelPos = prefs.getInt(
            ConfigActivity.KEY_VIDEO_ENCODE_BITRATE_LEVEL_POS,
            ConfigActivity.DEFAULT_VIDEO_ENCODE_BITRATE_LEVEL_POS
        )
        val encodeBitrateLevel =
            resources.getIntArray(R.array.encode_bitrate_level)[encodeBitrateLevelPos]
        val isHWCodecEnable = prefs.getBoolean(
            ConfigActivity.KEY_VIDEO_ENCODE_HARDWARE_CODEC_ENABLE,
            ConfigActivity.DEFAULT_VIDEO_HARDWARE_ENCODE_ENABLE
        )

        mVideoEncodeSetting = PLVideoEncodeSetting(this)
        mVideoEncodeSetting.setEncodingSizeLevel(encodingSizeLevel)
        mVideoEncodeSetting.setEncodingBitrate(encodeBitrateLevel)
        mVideoEncodeSetting.setHWCodecEnabled(isHWCodecEnable)
        mVideoEncodeSetting.setConstFrameRateEnabled(true)
    }

    private fun setAudioEncodeSetting() {
        val isHWCodecEnabled = prefs.getBoolean(
            ConfigActivity.KEY_AUDIO_ENCODE_HARDWARE_CODEC_ENABLE,
            ConfigActivity.DEFAULT_AUDIO_HARDWARE_ENCODE_ENABLE
        )
        val audioChannelNumPos = prefs.getInt(
            ConfigActivity.KEY_AUDIO_CHANNEL_NUM_POS,
            ConfigActivity.DEFAULT_AUDIO_CHANNEL_NUM_POS
        )
        val audioChannelNum = resources.getIntArray(R.array.audio_channel_num)[audioChannelNumPos]
        val audioEncodeBitrateLevelPos = prefs.getInt(
            ConfigActivity.KEY_AUDIO_ENCODE_BITRATE_LEVEL_POS,
            ConfigActivity.DEFAULT_AUDIO_ENCODE_BITRATE_LEVEL_POS
        )
        val audioEncodeBitrateLevel =
            resources.getIntArray(R.array.encode_bitrate_level)[audioEncodeBitrateLevelPos]
        val audioSampleRate = prefs.getInt(
            ConfigActivity.KEY_AUDIO_SAMPLE_RATE,
            ConfigActivity.DEFAULT_AUDIO_SAMPLE_RATE
        )

        mAudioEncodeSetting = PLAudioEncodeSetting()
        mAudioEncodeSetting.setHWCodecEnabled(isHWCodecEnabled)
        mAudioEncodeSetting.setChannels(audioChannelNum)
        mAudioEncodeSetting.setBitrate(audioEncodeBitrateLevel)
        mAudioEncodeSetting.setSampleRate(audioSampleRate)
    }

    private fun setMicrophoneSetting() {
        val samplingSampleRate = prefs.getInt(
            ConfigActivity.KEY_SAMPLING_SAMPLE_RATE,
            ConfigActivity.DEFAULT_SAMPLING_SAMPLE_RATE
        )
        val channelNumPos = prefs.getInt(
            ConfigActivity.KEY_SAMPLING_CHANNEL_NUM_POS,
            ConfigActivity.DEFAULT_SAMPLING_CHANNEL_NUM_POS
        )
        val channelNum = RecordSettings.SAMPLING_CHANNEL_NUM_ARRAY[channelNumPos]
        val samplingFormatPos = prefs.getInt(
            ConfigActivity.KEY_SAMPLING_FORMAT_POS,
            ConfigActivity.DEFAULT_SAMPLING_FORMAT_POS
        )
        val samplingFormat = RecordSettings.SAMPLING_FORMAT_ARRAY[samplingFormatPos]
        val samplingSourcePos = prefs.getInt(
            ConfigActivity.KEY_SAMPLING_SOURCE_POS,
            ConfigActivity.DEFAULT_SAMPLING_SOURCE_POS
        )
        val samplingSource = RecordSettings.SAMPLING_SOURCE_ARRAY[samplingSourcePos]
        val bluetoothSCOEnable = prefs.getBoolean(
            ConfigActivity.KEY_SAMPLING_BLUETOOTH_SCO_ENABLE,
            ConfigActivity.DEFAULT_SAMPLING_BLUETOOTH_SCO_ENABLE
        )
        val ptsOptimizeEnabled = prefs.getBoolean(
            ConfigActivity.KEY_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE,
            ConfigActivity.DEFAULT_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE
        )
        val isNSEnabled = prefs.getBoolean(
            ConfigActivity.KEY_SAMPLING_NSE_ENABLE,
            ConfigActivity.DEFAULT_SAMPLING_NSE_ENABLE
        )
        val isAECEnabled = prefs.getBoolean(
            ConfigActivity.KEY_SAMPLING_AEC_ENABLE,
            ConfigActivity.DEFAULT_SAMPLING_AEC_ENABLE
        )

        mMicrophoneSetting = PLMicrophoneSetting()
        mMicrophoneSetting.setSampleRate(samplingSampleRate)
        mMicrophoneSetting.setChannelConfig(channelNum)
        mMicrophoneSetting.setAudioFormat(samplingFormat)
        mMicrophoneSetting.setAudioSource(samplingSource)
        mMicrophoneSetting.setBluetoothSCOEnabled(bluetoothSCOEnable)
        mMicrophoneSetting.setPtsOptimizeEnabled(ptsOptimizeEnabled)
        mMicrophoneSetting.setNSEnabled(isNSEnabled)
        mMicrophoneSetting.setAECEnabled(isAECEnabled)
    }

    private fun setWatermarkSetting() {
        val watermarkSettingTypePos = prefs.getInt(
            ConfigActivity.KEY_WATERMARK_SETTING_TYPE_POS,
            ConfigActivity.DEFAULT_WATERMARK_SETTING_TYPE_POS
        )
        val watermarkAlpha =
            prefs.getInt(ConfigActivity.KEY_WATERMARK_ALPHA, ConfigActivity.DEFAULT_WATERMARK_ALPHA)
        val watermarkHeight = prefs.getFloat(
            ConfigActivity.KEY_WATERMARK_HEIGHT,
            ConfigActivity.DEFAULT_WATERMARK_HEIGHT
        )
        val watermarkWidth = prefs.getFloat(
            ConfigActivity.KEY_WATERMARK_WIDTH,
            ConfigActivity.DEFAULT_WATERMARK_WIDTH
        )
        val watermarkPositionX = prefs.getFloat(
            ConfigActivity.KEY_WATERMARK_POSITION_X,
            ConfigActivity.DEFAULT_WATERMARK_POSITION_X
        )
        val watermarkPositionY = prefs.getFloat(
            ConfigActivity.KEY_WATERMARK_POSITION_Y,
            ConfigActivity.DEFAULT_WATERMARK_POSITION_Y
        )

        if (watermarkSettingTypePos == 0) {
            // 0 代表关闭水印
            return
        } else if (watermarkSettingTypePos == 1) {
            mWatermarkSetting = PLWatermarkSetting()
            mWatermarkSetting.resourceId = R.drawable.qiniu_logo
        } else if (watermarkSettingTypePos == 2) {
            mWatermarkSetting = PLWatermarkSetting()
            val bitmap = BitmapFactory.decodeResource(resources, R.drawable.btn_flash_on)
            mWatermarkSetting.bitmap = bitmap
        }
        mWatermarkSetting.setSize(watermarkWidth, watermarkHeight)
        mWatermarkSetting.setPosition(watermarkPositionX, watermarkPositionY)
        mWatermarkSetting.alpha = watermarkAlpha
    }

    private fun setRecordSetting() {
        val maxRecordDuration = prefs.getLong(
            ConfigActivity.KEY_MAX_RECORD_DURATION,
            ConfigActivity.DEFAULT_MAX_RECORD_DURATION
        )
        val recordingSpeedVariableEnabled = prefs.getBoolean(
            ConfigActivity.KEY_RECORDING_SPEED_VARIABLE_ENABLED,
            ConfigActivity.DEFAULT_RECORDING_SPEED_VARIABLE_ENABLED
        )
        mRecordSetting = PLRecordSetting()
        mRecordSetting.setMaxRecordDuration(maxRecordDuration)
        mRecordSetting.setRecordSpeedVariable(recordingSpeedVariableEnabled)
        mRecordSetting.setVideoCacheDir(Config.VIDEO_STORAGE_DIR)
        mRecordSetting.setVideoFilepath(Config.RECORD_FILE_PATH)
    }

    private fun setFaceBeautySetting() {
        mFaceBeautySetting = PLFaceBeautySetting(1.0f, 0.5f, 0.5f)
    }

    private fun prepareAndSetShortVideoRecorder(preview: GLSurfaceView) {
        mShortVideoRecorder.prepare(
            preview, mCameraSetting, mMicrophoneSetting, mVideoEncodeSetting,
            mAudioEncodeSetting, mFaceBeautySetting, mRecordSetting
        )
        val isMirrorEncode = prefs.getBoolean(
            ConfigActivity.KEY_MIRROR_ENCODE_ENABLE,
            ConfigActivity.DEFAULT_MIRROR_ENCODE_ENABLE
        )
        mShortVideoRecorder.setMirrorForEncode(isMirrorEncode)
        setWatermarkSetting()
        if (::mWatermarkSetting.isInitialized) {
            mShortVideoRecorder.setWatermark(mWatermarkSetting)
        }
    }

    private fun getScreenRotation(orientation: Int): Int {
        var screenRotation = 0
        val isPortraitScreen =
            resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        if (orientation >= 315 || orientation < 45) {
            screenRotation = if (isPortraitScreen) 0 else 90
        } else if (orientation >= 45 && orientation < 135) {
            screenRotation = if (isPortraitScreen) 90 else 180
        } else if (orientation >= 135 && orientation < 225) {
            screenRotation = if (isPortraitScreen) 180 else 270
        } else if (orientation >= 225 && orientation < 315) {
            screenRotation = if (isPortraitScreen) 270 else 0
        }
        return screenRotation
    }

    private fun updateRecordingBtns(isRecording: Boolean) {
        binding.switchCamera.isEnabled = !isRecording
        binding.record.isActivated = isRecording
    }


    override fun onResume() {
        super.onResume()
        binding.record.isEnabled = false
        mShortVideoRecorder.resume()
    }

    override fun onPause() {
        super.onPause()
        updateRecordingBtns(false)
        mShortVideoRecorder.endSection()
        mShortVideoRecorder.pause()
    }

    override fun onDestroy() {
        super.onDestroy()
        mShortVideoRecorder.destroy(true)
        mOrientationListener.disable()
    }

    @SuppressLint("MissingSuperCall")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode == Activity.RESULT_OK && data!!.data != null) {
            val selectedFilepath = GetPathFromUri.getRealPathFromURI(this, data.data)
            Log.i(TAG, "Select file: $selectedFilepath")
            if (selectedFilepath != null && "" != selectedFilepath) {
                mShortVideoRecorder.setMusicFile(selectedFilepath)
                mShortVideoRecorder.setMusicLoop(mMusicLoop)
            }
        }
    }

    override fun onReady() {
        //mShortVideoRecorder.setFocusListener(this)
        runOnUiThread {
            binding.switchFlash.visibility =
                if (mShortVideoRecorder.isFlashSupport) View.VISIBLE else View.GONE
            mFlashEnabled = false
            binding.switchFlash.isActivated = mFlashEnabled
            binding.record.isEnabled = true
            refreshSeekBar()
        }
    }

    override fun onError(code: Int) {
        ToastUtils.showLong(code)
    }

    override fun onDurationTooShort() {
        binding.recordProgressbar.removeLastBreakPoint()
        runOnUiThread { ToastUtils.showLong("该视频段太短了") }
    }

    override fun onRecordStarted() {
        Log.i(TAG, "record start time: " + System.currentTimeMillis())
        mSectionBegan = true
        binding.recordProgressbar.setCurrentState(SectionProgressBar.State.START)
        runOnUiThread { updateRecordingBtns(true) }
    }

    override fun onRecordStopped() {
        Log.i(TAG, "record stop time: " + System.currentTimeMillis())
        mSectionBegan = false
        runOnUiThread { updateRecordingBtns(false) }
    }

    override fun onSectionRecording(
        sectionDurationMs: Long,
        videoDurationMs: Long,
        sectionCount: Int
    ) {
        Log.d(
            TAG,
            "sectionDurationMs: $sectionDurationMs; videoDurationMs: $videoDurationMs; sectionCount: $sectionCount"
        )
        updateRecordingPercentageView(videoDurationMs)
    }

    override fun onSectionIncreased(incDuration: Long, totalDuration: Long, sectionCount: Int) {
        Log.i(
            TAG,
            "section increased incDuration: $incDuration totalDuration: $totalDuration sectionCount: $sectionCount"
        )

        binding.recordProgressbar.addBreakPointTime(totalDuration)
        binding.recordProgressbar.setCurrentState(SectionProgressBar.State.PAUSE)
        updateRecordingPercentageView(totalDuration)
        onSectionCountChanged(sectionCount, totalDuration)
    }

    override fun onSectionDecreased(decDuration: Long, totalDuration: Long, sectionCount: Int) {
        Log.i(
            TAG,
            "section decreased decDuration: $decDuration totalDuration: $totalDuration sectionCount: $sectionCount"
        )
        binding.recordProgressbar.removeLastBreakPoint()
        updateRecordingPercentageView(totalDuration)
        onSectionCountChanged(sectionCount, totalDuration)
    }

    override fun onRecordCompleted() {
        runOnUiThread { ToastUtils.showLong("已达到拍摄总时长") }
    }

    override fun onProgressUpdate(percentage: Float) {
        runOnUiThread {
            mProcessingDialog!!.progress = (100 * percentage).toInt()
        }
    }

    override fun onSaveVideoFailed(errorCode: Int) {
        runOnUiThread {
            mProcessingDialog.dismiss()
            ToastUtils.showLong("拼接视频段失败: $errorCode")
        }
    }

    override fun onSaveVideoCanceled() {
        mProcessingDialog.dismiss()
    }

    override fun onSaveVideoSuccess(filePath: String) {
        Log.i(TAG, "concat sections success filePath: $filePath")
        MediaStoreUtils.storeVideo(this@VideoRecordActivity, File(filePath), "video/mp4")
        runOnUiThread {
            mProcessingDialog.dismiss()
            if (mIsEditVideo) {
                //VideoEditActivity.start(this@VideoRecordActivity, filePath)
            } else {
                val screenOrientation =
                    if ((ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE == requestedOrientation)) 0 else 1
                //PlaybackActivity.start(this@VideoRecordActivity, filePath, screenOrientation)
            }
        }
    }


    private fun updateRecordingPercentageView(currentDuration: Long) {
        runOnUiThread {
            val per = (100 * currentDuration / mRecordSetting.maxRecordDuration).toInt()
            binding.recordingPercentage.text = min(per.toDouble(), 100.0).toString() + "%"
        }
    }

    private fun refreshSeekBar() {
        val max = mShortVideoRecorder.maxExposureCompensation
        val min = mShortVideoRecorder.minExposureCompensation
        val brightnessAdjustAvailable = (max != 0 || min != 0)
        Log.e(
            TAG,
            "max/min exposure compensation: $max/$min brightness adjust available: $brightnessAdjustAvailable"
        )

        findViewById<View>(R.id.brightness_panel).visibility =
            if (brightnessAdjustAvailable) View.VISIBLE else View.GONE
        binding.adjustBrightness.max = (max + abs(min.toDouble())).toInt()
        binding.adjustBrightness.setProgress(abs(min.toDouble()).toInt())
        binding.adjustBrightness.setOnSeekBarChangeListener(if (!brightnessAdjustAvailable) null else object :
            OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
                if (i <= abs(min.toDouble())) {
                    mShortVideoRecorder.setExposureCompensation(i + min)
                } else {
                    mShortVideoRecorder.setExposureCompensation(i - max)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar) {
            }
        })
    }


    private fun showChooseDialog() {
        val builder = AlertDialog.Builder(this)
        builder.setTitle(getString(R.string.if_edit_video))
        builder.setPositiveButton(getString(R.string.dlg_yes)) { dialog: DialogInterface?, which: Int ->
            mIsEditVideo = true
            mShortVideoRecorder.concatSections(this@VideoRecordActivity)
        }
        builder.setNegativeButton(getString(R.string.dlg_no)) { dialog: DialogInterface?, which: Int ->
            mIsEditVideo = false
            mShortVideoRecorder.concatSections(this@VideoRecordActivity)
        }
        builder.setCancelable(false)
        builder.create().show()
    }

    private fun onSectionCountChanged(count: Int, totalTime: Long) {
        runOnUiThread {
            binding.delete.isEnabled = count > 0
            binding.concat.isEnabled = totalTime >= ConfigActivity.DEFAULT_MIN_RECORD_DURATION
        }
    }

    fun onSpeedClicked(view: View) {
        if (!mVideoEncodeSetting.IsConstFrameRateEnabled() || !mRecordSetting.IsRecordSpeedVariable()) {
            if (binding.recordProgressbar.isRecorded()) {
                ToastUtils.showLong("变帧率模式下，无法在拍摄中途修改拍摄倍数！")
                return
            }
        }

        if (mSectionBegan) {
            ToastUtils.showLong("一段视频只能是固定的录制速度！")
            return
        }

        mSpeedTextView.setTextColor(resources.getColor(R.color.speedTextNormal))


        val textView = view as TextView
        textView.setTextColor(resources.getColor(R.color.colorAccent))
        mSpeedTextView = textView

        when (view.getId()) {
            R.id.super_slow_speed_text -> mRecordSpeed = RECORD_SPEED_ARRAY[0]
            R.id.slow_speed_text -> mRecordSpeed = RECORD_SPEED_ARRAY[1]
            R.id.normal_speed_text -> mRecordSpeed = RECORD_SPEED_ARRAY[2]
            R.id.fast_speed_text -> mRecordSpeed = RECORD_SPEED_ARRAY[3]
            R.id.super_fast_speed_text -> mRecordSpeed = RECORD_SPEED_ARRAY[4]
            else -> {}
        }

        mShortVideoRecorder.setRecordSpeed(mRecordSpeed)
        binding.recordProgressbar.setProceedingSpeed(mRecordSpeed)
    }

    fun onScreenRotation(v: View?) {
        if (binding.delete.isEnabled) {
            ToastUtils.showLong("已经开始拍摄，无法旋转屏幕。")
        } else {
            requestedOrientation =
                if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
    }

    fun onCaptureFrame(v: View?) {
        mShortVideoRecorder.captureFrame { capturedFrame: PLVideoFrame? ->
            if (capturedFrame == null) {
                Log.e(TAG, "capture frame failed")
                return@captureFrame
            }
            Log.i(
                TAG,
                "captured frame width: " + capturedFrame.width + " height: " + capturedFrame.height + " timestamp: " + capturedFrame.timestampMs
            )
            try {
                val fos = FileOutputStream(Config.CAPTURED_FRAME_FILE_PATH)
                capturedFrame.toBitmap().compress(Bitmap.CompressFormat.JPEG, 100, fos)
                fos.close()
                runOnUiThread {
                    ToastUtils.showLong("截帧已保存到路径：" + Config.CAPTURED_FRAME_FILE_PATH)
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

}